using ERPBackend.Data;
using ERPBackend.Models;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Linq;
using System;

namespace ERPBackend.Services
{
    public class InventoryService : IInventoryService
    {
        private readonly ApplicationDbContext _context;

        public InventoryService(ApplicationDbContext context)
        {
            _context = context ?? throw new ArgumentNullException(nameof(context));
        }

        public async Task<IEnumerable<Inventory>> GetAllInventoriesAsync()
        {
            return await _context.Inventories
                .Include(i => i.Material)
                .Include(i => i.Warehouse)
                .ToListAsync() ?? Enumerable.Empty<Inventory>();
        }

        public async Task<Inventory?> GetInventoryByIdAsync(int id)
        {
            return await _context.Inventories
                .Include(i => i.Material)
                .Include(i => i.Warehouse)
                .FirstOrDefaultAsync(i => i.Id == id);
        }

        public async Task<Inventory?> GetInventoryByMaterialAndWarehouseAsync(int materialId, int warehouseId)
        {
            return await _context.Inventories
                .FirstOrDefaultAsync(i => i.MaterialId == materialId && i.WarehouseId == warehouseId);
        }

        public async Task<IEnumerable<Inventory>> GetInventoriesPagedAsync(int page, int pageSize)
        {
            int skip = (page - 1) * pageSize;
            return await _context.Inventories
                .Include(i => i.Material)
                .Include(i => i.Warehouse)
                .OrderBy(i => i.MaterialId)
                .Skip(skip)
                .Take(pageSize)
                .ToListAsync() ?? Enumerable.Empty<Inventory>();
        }

        public async Task<int> GetTotalInventoriesAsync()
        {
            return await _context.Inventories.CountAsync();
        }

        public async Task<Inventory> CreateInventoryAsync(Inventory inventory)
        {
            // 检查是否已存在相同的物料和仓库组合
            var existingInventory = await _context.Inventories
                .FirstOrDefaultAsync(i => i.MaterialId == inventory.MaterialId && i.WarehouseId == inventory.WarehouseId);
            if (existingInventory != null)
            {
                throw new ArgumentException("该物料在指定仓库中的库存记录已存在");
            }

            _context.Inventories.Add(inventory);
            await _context.SaveChangesAsync();
            return inventory;
        }

        public async Task<bool> UpdateInventoryAsync(Inventory inventory)
        {
            // 检查库存是否存在
            var existingInventory = await _context.Inventories.FindAsync(inventory.Id);
            if (existingInventory == null)
            {
                return false;
            }

            // 检查物料和仓库组合是否已被其他记录使用
            if (existingInventory.MaterialId != inventory.MaterialId || existingInventory.WarehouseId != inventory.WarehouseId)
            {
                if (await _context.Inventories.AnyAsync(i => i.MaterialId == inventory.MaterialId && i.WarehouseId == inventory.WarehouseId && i.Id != inventory.Id))
                {
                    throw new ArgumentException("该物料在指定仓库中的库存记录已存在");
                }
            }

            // 更新属性
            existingInventory.MaterialId = inventory.MaterialId;
            existingInventory.WarehouseId = inventory.WarehouseId;
            existingInventory.BatchNumber = inventory.BatchNumber;
            existingInventory.CurrentStock = inventory.CurrentStock;
            existingInventory.SafetyStock = inventory.SafetyStock;
            existingInventory.MaxStock = inventory.MaxStock;
            existingInventory.Unit = inventory.Unit;
            existingInventory.StockAmount = inventory.StockAmount;
            existingInventory.LastStockInDate = inventory.LastStockInDate;
            existingInventory.LastStockOutDate = inventory.LastStockOutDate;
            existingInventory.Status = inventory.Status;

            _context.Entry(existingInventory).State = EntityState.Modified;
            await _context.SaveChangesAsync();
            return true;
        }

        public async Task<bool> DeleteInventoryAsync(int id)
        {
            var inventory = await _context.Inventories.FindAsync(id);
            if (inventory == null)
            {
                return false;
            }

            _context.Inventories.Remove(inventory);
            await _context.SaveChangesAsync();
            return true;
        }

        public async Task<bool> UpdateInventoryQuantityAsync(int materialId, int warehouseId, decimal quantity, byte transactionType, string remark, int operatorId)
        {
            // 查找库存记录
            var inventory = await _context.Inventories
                .FirstOrDefaultAsync(i => i.MaterialId == materialId && i.WarehouseId == warehouseId);

            if (inventory == null)
            {
                // 如果库存记录不存在且是入库操作，则创建新记录
                if (quantity > 0)
                {
                    // 获取物料信息以填充单位
                    var material = await _context.Materials.FindAsync(materialId);
                    if (material == null)
                    {
                        return false;
                    }

                    inventory = new Inventory
                    {
                        MaterialId = materialId,
                        WarehouseId = warehouseId,
                        CurrentStock = quantity,
                        Unit = material.Unit,
                        Status = 1 // 正常状态
                    };
                    _context.Inventories.Add(inventory);
                }
                else
                {
                    throw new ArgumentException("库存不足");
                }
            }
            else
            {
                // 检查库存是否足够（出库操作）
                if (quantity < 0 && inventory.CurrentStock + quantity < 0)
                {
                    throw new ArgumentException("库存不足");
                }

                // 更新库存数量
                inventory.CurrentStock += quantity;

                // 更新最后出入库日期
                if (quantity > 0)
                {
                    inventory.LastStockInDate = DateTime.Now;
                }
                else
                {
                    inventory.LastStockOutDate = DateTime.Now;
                }

                // 更新库存状态
                if (inventory.CurrentStock < inventory.SafetyStock)
                {
                    inventory.Status = 0; // 预警
                }
                else if (inventory.CurrentStock > inventory.MaxStock)
                {
                    inventory.Status = 2; // 超储
                }
                else
                {
                    inventory.Status = 1; // 正常
                }

                _context.Entry(inventory).State = EntityState.Modified;
            }

            // 创建库存交易记录
                var transaction = new InventoryTransaction
                {
                    TransactionCode = GenerateTransactionCode(),
                    TransactionType = transactionType,
                    TransactionDate = DateTime.Now,
                    MaterialId = materialId,
                    WarehouseId = warehouseId,
                    TransactionQuantity = quantity,
                    BeforeStock = inventory.CurrentStock - quantity,
                    AfterStock = inventory.CurrentStock,
                    OperatorId = operatorId,
                    Remark = remark
                };
            _context.InventoryTransactions.Add(transaction);

            await _context.SaveChangesAsync();
            return true;
        }

        public async Task<IEnumerable<Inventory>> GetInventoryAlertsAsync()
        {
            return await _context.Inventories
                .Include(i => i.Material)
                .Include(i => i.Warehouse)
                .Where(i => i.Status != 1) // 非正常状态
                .ToListAsync() ?? Enumerable.Empty<Inventory>();
        }

        public async Task<IEnumerable<InventoryTransaction>> GetInventoryTransactionsAsync(int materialId, int warehouseId)
        {
            return await _context.InventoryTransactions
                .Include(t => t.Material)
                .Include(t => t.Warehouse)
                .Include(t => t.Operator)
                .Where(t => t.MaterialId == materialId && t.WarehouseId == warehouseId)
                .OrderByDescending(t => t.TransactionDate)
                .ToListAsync() ?? Enumerable.Empty<InventoryTransaction>();
        }

        private string GenerateTransactionCode()
        {
            // 生成唯一的交易编码
            return "TXN" + DateTime.Now.ToString("yyyyMMddHHmmss") + Guid.NewGuid().ToString("N").Substring(0, 4);
        }
    }
}